home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 1833 / 1833.xpi / modules / yoonoKeyValueDB.js < prev    next >
Text File  |  2009-12-16  |  10KB  |  301 lines

  1. var EXPORTED_SYMBOLS = ["YOONO_KEYVALUEDB"];
  2.  
  3. Components.utils.import("resource://yoono/yoonoLog.js");
  4. var log = YOONO_LOG;
  5.  
  6. const YOONO_DIR       = "yoono";
  7. const YOONO_DB_FILE   = "anonUser.sqlite";  // new user nb name
  8.  
  9. const PERMS_FILE      = 0655;
  10.  
  11. const CI = Components.interfaces;
  12. const CL = Components.classes;
  13.  
  14. const DIRSERVICE = CL['@mozilla.org/file/directory_service;1'].getService(CI.nsIProperties);
  15.  
  16.  
  17. const YOONO_KEYVALUEDB = {};
  18.  
  19. YOONO_KEYVALUEDB.getCurrentDBFileName = function() {
  20.   return(this.dbFileName);
  21. };
  22.  
  23. YOONO_KEYVALUEDB.getDBFileName = function() {
  24.   var dbFileName = this.loginToFileName() + '.sqlite';
  25.   return(dbFileName);
  26. };
  27.  
  28. YOONO_KEYVALUEDB.loginToFileName = function() {
  29.   Components.utils.import("resource://yoono/yoonoService.js"); // strangely needed here too
  30.   var fileName = 'anonUser';
  31.   var userData = YOONO_CMPT.getUserCredential();
  32.   if(userData && !userData.anonymous) {
  33.     fileName = YOONO_CMPT.escapeFileName(userData.login);
  34.   }
  35.   return(fileName);
  36. }
  37.  
  38. /**
  39.  * This method closes the database, renames the current file to the new file, and reopens the database
  40.  */
  41. YOONO_KEYVALUEDB.switchDB = function() {
  42.   this.closeDB();
  43.   var currentFileName = this.getDBFileName();
  44.   var filePath = YOONO_DIRSERVICE.get("ProfDS", CI.nsIFile)
  45.   filePath.append('yoono');
  46.   var currentFile = filePath.clone();
  47.   var newFilePath = filePath.clone();
  48.   currentFile.append(currentFileName);
  49.   var newFileName = this.getDBFileName();
  50.   newFilePath.append(newFileName);
  51.   if(newFilePath.exists()) {
  52.     newFilePath.remove(false);
  53.   }  
  54.   currentFile.moveTo(filePath, newFileName);
  55.   // DB will be reopenned when it's needed
  56. }
  57.  
  58. // this is called only if this DB is needed
  59. YOONO_KEYVALUEDB.initDB = function() {
  60.   try {
  61.     if(this.mDBConn) return;
  62.     log.debug("Initializing DB");
  63.     var dbFile = DIRSERVICE.get("ProfDS", CI.nsIFile)
  64.     dbFile.append(YOONO_DIR);
  65.     var userDbFile = dbFile.clone();
  66.     dbFile.append(YOONO_DB_FILE);
  67.     this.dbFileName = this.getDBFileName();
  68.     userDbFile.append(this.dbFileName);
  69.  
  70.     // If default anonUser.sqlite file exists and no username.sqlite file exists
  71.     // rename the former to the latter
  72.     if(dbFile.exists() && !userDbFile.exists()) {
  73.       dbFile.moveTo(null, this.dbFileName);
  74.     }
  75.  
  76.     dbFile = DIRSERVICE.get("ProfDS", CI.nsIFile)
  77.     dbFile.append(YOONO_DIR);
  78.     dbFile.append(this.dbFileName);
  79.  
  80.     // database not yet created : create it !
  81.     var creation = false;
  82.     if(!dbFile.exists()) {
  83.       dbFile.create(CI.nsIFile.NORMAL_FILE_TYPE, PERMS_FILE);
  84.       creation = true;
  85.     }
  86.     var storageService = CL["@mozilla.org/storage/service;1"].getService(CI.mozIStorageService);
  87.     this.mDBConn = storageService.openDatabase(dbFile);
  88.     // statements will be initialized the first time they are needed... they might never be...
  89.     this.getKeyValueStatement = null;
  90.     this.setKeyValueStatement = null;
  91.     this.deleteKeyValueStatement = null;
  92.     this.getKeyValueListStatement = null;
  93.     if(creation) {
  94.       this.mDBConn.executeSimpleSQL("CREATE TABLE keyvalues (key STRING PRIMARY KEY, value STRING, expire INTEGER)");
  95.     }
  96.   } catch(e) {
  97.     log.exception(e);
  98.     this.mDBConn = null;
  99.   }
  100. };
  101.  
  102. YOONO_KEYVALUEDB.closeDB = function() {
  103.   try {
  104.     if(!this.mDBConn) return;
  105.  
  106.     log.debug("Closing DB");
  107.     // Since Gecko 1.9M9, must call finalize on statements before closing 
  108.     if((null != this.getKeyValueStatement) && ('finalize' in this.getKeyValueStatement))
  109.       this.getKeyValueStatement.finalize();
  110.     if((null != this.setKeyValueStatement) && ('finalize' in this.setKeyValueStatement))
  111.       this.setKeyValueStatement.finalize();
  112.     if((null != this.deleteKeyValueStatement) && ('finalize' in this.deleteKeyValueStatement))
  113.       this.deleteKeyValueStatement.finalize();
  114.     if((null != this.getKeyValueListStatement) && ('finalize' in this.getKeyValueListStatement))
  115.       this.getKeyValueListStatement.finalize();
  116.  
  117.     this.getKeyValueStatement = null;
  118.     this.setKeyValueStatement = null;
  119.     this.deleteKeyValueStatement = null;
  120.     this.getKeyValueListStatement = null;
  121.     
  122.     // Commit current transaction
  123.     if (this.commitTimer)
  124.       this.commitTimer.stop();
  125.     
  126.     // Since Gecko 1.9M8, must call close on db
  127.     if('close' in this.mDBConn)
  128.       this.mDBConn.close();
  129.     
  130.     log.debug("DB Closed!");
  131.     
  132.     this.mDBConn = null;
  133.   } catch(e) {
  134.     log.exception(e);
  135.   }
  136. }
  137.  
  138. YOONO_KEYVALUEDB.getKeyValue = function(key) {
  139.   var value = null;
  140.   var expire = 0;
  141.   try {
  142.     this.initDB();
  143.     if(!this.mDBConn) return value;
  144.     if(!this.getKeyValueStatement) {
  145.       this.getKeyValueStatement = this.mDBConn.createStatement("SELECT value, expire FROM keyvalues where key = ?1");
  146.     }
  147.     this.getKeyValueStatement.bindUTF8StringParameter(0, key);
  148.     var now = Math.floor((new Date().getTime())/1000);
  149.     // there should be only one...
  150.     while (this.getKeyValueStatement.executeStep()) {
  151.       value = this.getKeyValueStatement.getUTF8String(0);
  152.       expire = this.getKeyValueStatement.getInt32(1);
  153.     }
  154.   } catch(e) {
  155.     log.exception(e);
  156.   } finally {
  157.     this.getKeyValueStatement.reset();
  158.   }
  159.   if((expire != 0) && (expire <= now)) {
  160.     log.debug('Deleting expired key : ' + key + '=' + value);
  161.     this.deleteKeyValue(key);
  162.     value = null;
  163.   } else {
  164.     /*
  165.     var logVal = value;
  166.     if(value && (value.length>500)) {
  167.       logVal = value.substr(0, 230) + ' [... VALUE TOO LARGE TO BE LOGGED ...] ' + value.substr(value.length - 250);
  168.     }
  169.     log.debug('Key found : ' + key + ' valid till ' + expire + ', value : ' + logVal);
  170.     */
  171.   }
  172.   return(value);
  173.  
  174. };
  175.  
  176. YOONO_KEYVALUEDB.deleteKeyValue = function(key) {
  177.   try {
  178.     this.initDB();
  179.     if(!this.mDBConn) return;
  180.     if(!this.deleteKeyValueStatement) {
  181.       this.deleteKeyValueStatement = this.mDBConn.createStatement("DELETE FROM keyvalues WHERE key = ?1");
  182.     }
  183.     this.deleteKeyValueStatement.bindUTF8StringParameter(0, key);
  184.     this.deleteKeyValueStatement.execute();
  185.   } catch(e) {
  186.     log.exception(e);
  187.   } finally {
  188.     // if error before execute, reset might be needed ?
  189.     this.deleteKeyValueStatement.reset();
  190.   }
  191. };
  192.  
  193. // saving a key/value pair in the sqlite database
  194. // expire is the number of day the data is valid. After that, it will be erased when accessed
  195. YOONO_KEYVALUEDB.setKeyValue = function(key, value, daysValid) {
  196.   this.initDB();
  197.   if(!this.mDBConn) return;
  198.   
  199.   if (!this.mDBConn.transactionInProgress)
  200.     this.mDBConn.beginTransactionAs(this.mDBConn.TRANSACTION_DEFERRED);
  201.   
  202.   try { 
  203.     var expire = 0;
  204.     if(daysValid) {
  205.       var now = Math.floor((new Date().getTime())/1000);
  206.       expire = now + (daysValid * 86400); // 86400 seconds in a day
  207.     }
  208.     if(! this.setKeyValueStatement) {
  209.       this.setKeyValueStatement = this.mDBConn.createStatement("INSERT OR REPLACE INTO keyvalues VALUES (?1, ?2, ?3) ");
  210.     }
  211.     this.setKeyValueStatement.bindUTF8StringParameter(0, key);
  212.     this.setKeyValueStatement.bindUTF8StringParameter(1, value);
  213.     this.setKeyValueStatement.bindInt32Parameter(2, expire);
  214.     this.setKeyValueStatement.execute();
  215.   } catch(e) {
  216.     log.error('YOONO_CMPT.setKeyValue : ' + e);
  217.   } finally {
  218.     // if error before execute, reset might be needed ?
  219.     this.setKeyValueStatement.reset();
  220.   }
  221.   
  222.   if (!this.commitTimer) {
  223.     var self=this;
  224.     this.commitTimer={
  225.       timeout : 2000,
  226.       timer : CL['@mozilla.org/timer;1'].createInstance(CI.nsITimer),
  227.       start : function () {
  228.         this.timer.initWithCallback(this, this.timeout, this.timer.TYPE_ONE_SHOT);
  229.       },
  230.       stop : function () {
  231.         this.timer.cancel();
  232.         self.mDBConn.commitTransaction();
  233.         self.commitTimer=null;
  234.       },
  235.       notify : function(timer) {
  236.         try {
  237.           self.mDBConn.commitTransaction();
  238.           self.commitTimer=null;
  239.         } catch(e) {
  240.           log.exception(e);
  241.         }
  242.       }
  243.     };
  244.     this.commitTimer.start();
  245.   }
  246.   
  247.   /*
  248.   var logVal = value;
  249.   if(value && (value.length>500)) {
  250.     logVal = value.substr(0, 230) + ' [... VALUE TOO LARGE TO BE LOGGED ...] ' + value.substr(value.length - 250);
  251.   }
  252.   log.debug('Key saved : ' + key + ' value ' + logVal);
  253.   */
  254. };
  255.  
  256. YOONO_KEYVALUEDB.getKeyValueList = function(keyPrefix) {
  257.   var result = new Object();
  258.   try {
  259.     this.initDB();
  260.     if(!this.mDBConn) return result;
  261.     if(! this.getKeyValueListStatement) {
  262.       this.getKeyValueListStatement = this.mDBConn.createStatement('SELECT key, value, expire FROM keyvalues WHERE key LIKE ?1');
  263.     }
  264.     log.debug('Key prefix search : ' + keyPrefix);
  265.     this.getKeyValueListStatement.bindUTF8StringParameter(0, keyPrefix + '%');
  266.     var value = '';
  267.     var key = '';
  268.     var expire = 0;
  269.     var now = Math.floor((new Date().getTime())/1000);
  270.     var toDelete = new Array();
  271.     while (this.getKeyValueListStatement.executeStep()) {
  272.       key = this.getKeyValueListStatement.getUTF8String(0);
  273.       value = this.getKeyValueListStatement.getUTF8String(1);
  274.       expire = this.getKeyValueListStatement.getInt32(2);
  275.       if((expire != 0) && (expire <= now)) {
  276.         /*
  277.         if(YOONO_PREFS.get('debug.level') >4) // save perf on string concat in loops
  278.           log.debug('Deleting expired (' + expire + ') key : ' + key + '=' + value);
  279.         */
  280.         // can't delete in table while reading cursor is open
  281.         toDelete.push(key);
  282.       } else {
  283.         result[key] = value;
  284.         /*
  285.         if(YOONO_PREFS.get('debug.level') >4) // save perf on string concat in loops
  286.           log.debug('Key found : ' + key + ' valid till ' + expire);
  287.         */
  288.       }
  289.     }
  290.   } catch(e) {
  291.     log.exception(e);
  292.   } finally {
  293.     this.getKeyValueListStatement.reset();
  294.   }
  295.   // deleting expired values found
  296.   for(var i=0 ; i < toDelete.length; i++) {
  297.     this.deleteKeyValue(toDelete[i]);
  298.   }
  299.   return result;
  300. };
  301.